#include "PWM.H"  // 包含PWM模块的头文件，声明了本文件中实现的函数和相关宏定义

/**
    ******************************************************************************
    * @brief  配置TIM2通道2为PWM输出模式，初始化相关硬件
    * @param  无
    * @retval 无
    * @note   输出引脚: PA1 (TIM2_CH2)，对应定时器2的通道2
    *         PWM频率: 1kHz（通过时基参数计算得出）
    *         占空比范围: 0.0% - 100.0%（共100级可调）
    *         系统时钟: 72MHz（STM32F10x系列默认最高系统时钟）
    ******************************************************************************
*/
void PWM_Config(void)
{
    // 使能外设时钟：
    // - PWM_CLK：通过宏定义指定为GPIOA的时钟（RCC_APB2Periph_GPIOA），控制PA1引脚
    // - RCC_APB2Periph_AFIO：复用功能时钟，必须使能才能将PA1与TIM2_CH2绑定
    RCC_APB2PeriphClockCmd(PWM_CLK | RCC_APB2Periph_AFIO, ENABLE);
    
    // 定义GPIO初始化结构体，用于配置PA1引脚
    GPIO_InitTypeDef GPIO_InitStructure = {
        .GPIO_Mode  = GPIO_Mode_AF_PP,   // 复用推挽输出模式：
                                         // - 复用(AF)：引脚控制权交给定时器外设，而非普通GPIO
                                         // - 推挽(PP)：可输出高/低电平，驱动能力强（适合PWM信号）
        .GPIO_Pin   = PWM_PIN,           // 通过宏定义指定为PA1（TIM2_CH2的默认复用引脚）
        .GPIO_Speed = GPIO_Speed_50MHz,  // 引脚翻转速度50MHz：
                                         // - 高于PWM频率(1kHz)，确保波形无失真
                                         // - 50MHz是STM32F10x通用GPIO的高速模式
    };
    // 根据结构体配置GPIOA端口（PA1引脚）
    GPIO_Init(PWM_PORT, &GPIO_InitStructure);  // PWM_PORT通过宏定义指定为GPIOA
    
    // 使能TIM2定时器的时钟：
    // - TIM2属于APB1总线外设，时钟由RCC_APB1Periph_TIM2控制
    // - APB1总线默认时钟为36MHz，但定时器时钟=APB1时钟×2=72MHz（当APB1分频系数≠1时）
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 配置TIM2使用内部时钟源（CK_INT）：
    // 内部时钟路径：SYSCLK(72MHz) → AHB总线(不分频) → APB1总线(分频2) → TIM2时钟(72MHz)
    // 此函数会将TIM2的时钟源设置为内部时钟（默认也是内部时钟，此处显式配置更清晰）
    TIM_InternalClockConfig(TIM2);

    // 定义定时器时基初始化结构体，用于配置PWM频率
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {
        // TIM_ClockDivision：时钟分频因子，用于定时器的采样时钟（与输入捕获的滤波相关）
        // - TIM_CKD_DIV1：不分频，采样时钟=定时器时钟（本项目无用，因不涉及输入捕获）
        .TIM_ClockDivision = TIM_CKD_DIV1,    
        
        // TIM_CounterMode：计数模式
        // - TIM_CounterMode_Up：向上计数，计数器从0递增到ARR，再重置为0循环
        .TIM_CounterMode = TIM_CounterMode_Up,
        
        // TIM_Period：自动重载值（ARR寄存器）
        // - 取值为100-1=99，即计数器计数到99时触发更新事件并重置
        // - 计数周期包含的计数值=ARR+1=100，决定PWM的分辨率（100级）
        .TIM_Period = 100 - 1,
        
        // TIM_Prescaler：预分频器值（PSC寄存器）
        // - 取值为720-1=719，用于对定时器时钟分频
        // - 分频后定时器的计数时钟=72MHz/(720)=100kHz
        .TIM_Prescaler = 720 - 1,
        
        // TIM_RepetitionCounter：重复计数器
        // - 仅高级定时器（如TIM1、TIM8）有效，通用定时器（如TIM2）无此功能，必须设为0
        .TIM_RepetitionCounter = 0,           
    };
    // 将时基参数应用到TIM2定时器（写入相关寄存器）
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

    // 定义输出比较结构体，用于配置PWM模式
    TIM_OCInitTypeDef TIM_OCInitStructure;
    // 初始化结构体为默认值：
    // - 避免结构体中未显式赋值的成员（如TIM_OCIdleState）为随机值导致配置错误
    // - 默认值包括：关闭输出、冻结模式、高电平极性等
    TIM_OCStructInit(&TIM_OCInitStructure);
    
    // 配置TIM2通道2为PWM模式1：
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1规则：
                                                       // - 当计数器值(CNT) < 比较值(CCR2)时，输出有效电平（高电平）
                                                       // - 当CNT >= CCR2时，输出无效电平（低电平）
    
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性：高电平为有效电平
                                                               // 与PWM模式配合，决定有效电平的高低
    
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  // 使能通道2的输出：
                                                                   // 允许PWM信号从引脚输出
    
    TIM_OCInitStructure.TIM_Pulse = 0;  // 初始比较值（CCR2寄存器）：
                                        // - 取值为0，即初始占空比=0%（输出始终为低电平）
                                        // - 后续可通过PWM_SetCompare2函数修改此值
    
    // 将输出比较参数应用到TIM2的通道2（对应PA1引脚）
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    
    // 使能TIM2的自动重载预装载功能：
    // - 配置ARPE位=1，使ARR寄存器的值在更新事件（计数器重置时）才生效
    // - 避免在计数过程中修改ARR导致PWM周期突变
    TIM_ARRPreloadConfig(TIM2, ENABLE);
    
    // 使能TIM2通道2的输出比较预装载功能：
    // - 配置OC2PE位=1，使CCR2寄存器的值在更新事件时生效
    // - 避免在PWM周期中途修改CCR2导致占空比突变（如波形出现毛刺）
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

    // 启动TIM2定时器：
    // - 写入CR1寄存器的CEN位=1，允许计数器开始计数
    // - 计数器启动后，PWM信号开始从PA1引脚输出
    TIM_Cmd(TIM2, ENABLE);
}

/**
    ******************************************************************************
    * @brief  设置TIM2通道2的PWM占空比，通过修改比较寄存器(CCR2)实现
    * @param  Compare: 比较值（写入CCR2寄存器），范围必须为0~99
    * @retval 无
    * @note   占空比计算公式: 占空比 = (Compare / 99) × 100%
    *         例如: 
    *         - Compare=0 → 占空比=0%（始终输出低电平）
    *         - Compare=49 → 占空比≈49.5%（高电平持续49个计数周期）
    *         - Compare=99 → 占空比=100%（始终输出高电平）
    ******************************************************************************
*/
void PWM_SetCompare2(u16 Compare)
{
    // 直接向TIM2的通道2比较寄存器(CCR2)写入值：
    // - 此值决定PWM的占空比，与计数器(CNT)实时比较
    // - 由于使能了预装载功能，新值会在下次更新事件（CNT=99→0时）生效
    TIM_SetCompare2(TIM2, Compare);
}

/**
    ******************************************************************************
    * @brief  动态修改TIM2的预分频器值，实现PWM频率的调整
    * @param  Prescaler: 预分频器值（写入PSC寄存器），范围0~65535（16位寄存器最大值）
    * @retval 无
    * @note   实际PWM频率计算公式: 
    *         频率 = 定时器时钟 / ( (Prescaler + 1) × (ARR + 1) )
    *         = 72MHz / ( (Prescaler+1) × 100 )
    *         示例: 
    *         - 当Prescaler=719时 → 频率=72MHz/(720×100)=1kHz（默认配置）
    *         - 当Prescaler=359时 → 频率=72MHz/(360×100)=2kHz
    ******************************************************************************
*/
void PWM_SetPrescaler(u16 Prescaler)
{
    // 配置TIM2的预分频器：
    // - 第一个参数：目标定时器（TIM2）
    // - 第二个参数：预分频值（写入PSC寄存器）
    // - 第三个参数：更新模式（TIM_PSCReloadMode_Update）→ 新值立即生效
    TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Update);
}
